# import socket
# import threading
#
#
# class Chatroom:
#
#     def __init__(self):
#         self.ss=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
#         self.conn_list=[]
#
#     def start(self,bind_addr =('0.0.0.0',12345)):
#         self.ss.bind(bind_addr)
#         self.ss.listen()
#         self.communicate()
#
#     def communicate(self):
#         while True:
#             conn,addr=self.ss.accept()
#             if conn not in self.conn_list:
#                 print('{}链接进入：'.format(addr[0]))
#                 self.conn_list.append(conn)
#                 try:
#                     threading.Thread(target=self.receive_msg,args=(conn,addr)).start()
#                 except Exception as e:
#                     print('发生错误：{}'.format(e))
#
#     def receive_msg(self,conn,addr):
#         while True:
#             try:
#                 msg=conn.recv(65535)
#                 msg_de = msg.decode()
#                 ip = addr[0]
#                 print('收到来自{}的消息：{}'.format(ip, msg_de))
#                 reply_msg = '{}说：{}'.format(ip, msg.decode()).encode()
#                 self.reply_msg(reply_msg)
#             except Exception as e:
#                 print("{}发生错误,已退出".format(addr[0]))
#                 conn.close()
#                 break
#
#
#     def reply_msg(self,msg):
#         for i in self.conn_list:
#             try:
#                 i.send(msg)
#             except Exception:
#                 self.conn_list.remove(i)
#
#
# if __name__ == '__main__':
#     chatromm=Chatroom()
#     chatromm.start()
import socket
import threading


class Server:

    def __init__(self,port = 12345):
        self.ss = None
        self.ip = "0.0.0.0"
        self.port = port
        self.conn_list = []

    def start(self):
        """
        专门去启动各种服务
        :return:
        """
        try:
            self.start_server()
        except Exception as e:
            print(e)

            print('服务器启动失败')
            return
            # 启动循环 不断的接收链接
        print('服务启动成功')
        self.loop_recv_conn()

    def start_server(self):
        """
        启动tcp服务
        :return:
        """
        self.ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.ss.bind((self.ip, self.port))
        self.ss.listen()

    def recv_conn(self):
        """
        这个函数专门用来接收链接
        :return:
        """
        conn, addr = self.ss.accept()
        self.append_conn(conn, addr)
        return conn, addr

    def append_conn(self, conn, addr):
        """
        把conn加入到所有的conn列表里面取
        :return:
        """
        if conn not in self.conn_list:
            self.conn_list.append(conn)

    def loop_recv_conn(self):
        """
        这个函数专门用来不断的接收链接
        :return:
        """
        while 1:
            conn, addr = self.recv_conn()
            threading.Thread(target=self.process_conn, args=(conn, addr)).start()

    def process_conn(self, conn, addr):
        while 1:
            try:
                msg = conn.recv(65535)
            except Exception as e:
                self.error_handling(conn, e)
                continue
            ip, _ = addr
            return_msg = "来自{}ip的学生说:{}".format(ip, msg.decode())
            self.broadcast_msg(return_msg)

    def broadcast_msg(self, msg):
        """
        向所有的链接广播消息
        :param msg:
        :return:
        """
        for i in self.conn_list:
            self.send_msg(msg, i)

    def send_msg(self, msg, conn):
        """
        发送消息
        :param msg:
        :param conn:
        :return:
        """
        try:
            conn.send(msg.encode())
        except Exception as e:
            self.error_handling(conn, e)

    def error_handling(self, conn, e):
        """
        链接发送错误的逻辑处理
        :param conn:
        :return:
        """
        if conn in self.conn_list:
            self.conn_list.remove(conn)
        self.log_error(e)

    def log_error(self, e):
        """
        记录错误日志
        :param e:
        :return:
        """
        print(e)


if __name__ == "__main__":
    ss = Server()
    ss.start()




